package controllers

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"regexp"
	"shudao-chat-go/models"
	"shudao-chat-go/utils"
	"strings"
	"time"

	// chroma "github.com/amikos-tech/chroma-go"
	"github.com/beego/beego/v2/server/web"
)

type ChatController struct {
	web.Controller
}

// 阿里大模型聊天函数
func (c *ChatController) sendQwen3Message(userMessage string, useStream bool) (string, error) {
	// 从Beego配置读取阿里大模型配置
	apiURL, err := web.AppConfig.String("qwen3_api_url")
	if err != nil || apiURL == "" {
		return "", fmt.Errorf("配置文件中未找到qwen3_api_url")
	}

	model, err := web.AppConfig.String("qwen3_model")
	if err != nil || model == "" {
		return "", fmt.Errorf("配置文件中未找到qwen3_model")
	}

	// 在用户消息后面添加字数限制要求
	finalMessage := userMessage
	fmt.Println("最终发送的消息:", finalMessage)

	// 创建阿里大模型请求
	qwen3Request := map[string]interface{}{
		"model":       model,
		"stream":      useStream,
		"temperature": 0.7,
		"messages": []map[string]string{
			{"role": "system", "content": "你是一个乐于助人的助手。"},
			{"role": "user", "content": finalMessage},
		},
	}

	// 序列化请求
	requestBody, err := json.Marshal(qwen3Request)
	if err != nil {
		return "", fmt.Errorf("请求序列化失败: %v", err)
	}

	// 发送HTTP请求到阿里大模型
	req, err := http.NewRequest("POST", apiURL+"/v1/chat/completions", bytes.NewBuffer(requestBody))
	if err != nil {
		return "", fmt.Errorf("创建HTTP请求失败: %v", err)
	}

	// 设置请求头
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	client := &http.Client{Timeout: 600 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("请求发送失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		responseBody, _ := io.ReadAll(resp.Body)
		return "", fmt.Errorf("阿里大模型API错误: %s", string(responseBody))
	}

	if useStream {
		// 处理流式响应
		return c.handleStreamResponse(resp)
	} else {
		// 处理非流式响应
		return c.handleNonStreamResponse(resp)
	}
}

// 处理流式响应
func (c *ChatController) handleStreamResponse(resp *http.Response) (string, error) {
	// 定义流式响应结构
	type StreamResponse struct {
		ID      string `json:"id"`
		Object  string `json:"object"`
		Created int64  `json:"created"`
		Model   string `json:"model"`
		Choices []struct {
			Index int `json:"index"`
			Delta struct {
				Role      string `json:"role,omitempty"`
				Content   string `json:"content,omitempty"`
				ToolCalls []struct {
					Index    int    `json:"index"`
					ID       string `json:"id"`
					Type     string `json:"type"`
					Function struct {
						Name      string `json:"name"`
						Arguments string `json:"arguments"`
					} `json:"function"`
				} `json:"tool_calls,omitempty"`
			} `json:"delta"`
			Logprobs     interface{} `json:"logprobs"`
			FinishReason *string     `json:"finish_reason"`
			StopReason   *string     `json:"stop_reason,omitempty"`
		} `json:"choices"`
	}

	// 逐行读取流式响应
	scanner := bufio.NewScanner(resp.Body)
	var fullContent strings.Builder
	var firstChunk = true

	for scanner.Scan() {
		line := scanner.Text()

		// 跳过空行和data:前缀
		if line == "" || !strings.HasPrefix(line, "data: ") {
			continue
		}

		// 移除"data: "前缀
		data := strings.TrimPrefix(line, "data: ")

		// 检查是否是结束标记
		if data == "[DONE]" {
			break
		}

		// 解析JSON数据
		var streamResp StreamResponse
		if err := json.Unmarshal([]byte(data), &streamResp); err != nil {
			continue // 跳过解析失败的数据
		}

		// 标记第一个块已处理
		if firstChunk {
			firstChunk = false
		}

		// 处理choices中的内容
		if len(streamResp.Choices) > 0 {
			choice := streamResp.Choices[0]
			if choice.Delta.Content != "" {
				fullContent.WriteString(choice.Delta.Content)
			}

			// 检查是否完成
			if choice.FinishReason != nil {
				break
			}
		}
	}

	if err := scanner.Err(); err != nil {
		return "", fmt.Errorf("读取流式响应失败: %v", err)
	}

	return fullContent.String(), nil
}

// 处理非流式响应
func (c *ChatController) handleNonStreamResponse(resp *http.Response) (string, error) {
	// 定义非流式响应结构（与测试文件中的Qwen3ChatResponse保持一致）
	type Qwen3ChatResponse struct {
		ID      string `json:"id"`
		Object  string `json:"object"`
		Created int64  `json:"created"`
		Model   string `json:"model"`
		Choices []struct {
			Index   int `json:"index"`
			Message struct {
				Role             string        `json:"role"`
				Content          string        `json:"content"`
				Refusal          *string       `json:"refusal"`
				Annotations      *string       `json:"annotations"`
				Audio            *string       `json:"audio"`
				FunctionCall     *string       `json:"function_call"`
				ToolCalls        []interface{} `json:"tool_calls"`
				ReasoningContent *string       `json:"reasoning_content"`
			} `json:"message"`
			Logprobs     *string `json:"logprobs"`
			FinishReason string  `json:"finish_reason"`
			StopReason   *string `json:"stop_reason"`
		} `json:"choices"`
		ServiceTier       *string `json:"service_tier"`
		SystemFingerprint *string `json:"system_fingerprint"`
		Usage             struct {
			PromptTokens        int     `json:"prompt_tokens"`
			TotalTokens         int     `json:"total_tokens"`
			CompletionTokens    int     `json:"completion_tokens"`
			PromptTokensDetails *string `json:"prompt_tokens_details"`
		} `json:"usage"`
		PromptLogprobs   *string `json:"prompt_logprobs"`
		KvTransferParams *string `json:"kv_transfer_params"`
	}

	// 读取完整的响应内容
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应失败: %v", err)
	}

	// 解析JSON响应
	var response Qwen3ChatResponse
	if err := json.Unmarshal(responseBody, &response); err != nil {
		return "", fmt.Errorf("响应解析失败: %v", err)
	}

	// 验证响应
	if response.ID == "" {
		return "", fmt.Errorf("响应ID为空")
	}
	if len(response.Choices) == 0 {
		return "", fmt.Errorf("响应中没有选择项")
	}

	return response.Choices[0].Message.Content, nil
}

// 发送deepseek消息
// 构造一下message、ai_conversation_id、user_id的结构体
type SendDeepSeekMessageRequest struct {
	Message          string `json:"message"`
	AIConversationId uint64 `json:"ai_conversation_id"`
	UserId           uint64 `json:"user_id"`
	BusinessType     int    `json:"business_type"`
	ExamName         string `json:"exam_name"`
}

func (c *ChatController) SendDeepSeekMessage() {
	// 从请求体获取消息
	var requestData SendDeepSeekMessageRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	fmt.Println("请求数据:", requestData)

	userMessage := requestData.Message
	var userMessage1 string
	userMessage1 = userMessage
	user_id := requestData.UserId
	if user_id == 0 {
		user_id = 1
	}
	ai_conversation_id := requestData.AIConversationId
	tx := models.DB.Begin()
	if ai_conversation_id == 0 {
		//新建对话
		ai_conversation := models.AIConversation{
			UserId:       user_id,
			Content:      userMessage,
			BusinessType: requestData.BusinessType,
			ExamName:     requestData.ExamName,
		}
		if err := tx.Create(&ai_conversation).Error; err != nil {
			tx.Rollback()
			c.Data["json"] = map[string]interface{}{
				"statusCode": 500,
				"msg":        "新建对话失败: " + err.Error(),
			}
			c.ServeJSON()
			return
		}
		ai_conversation_id = uint64(ai_conversation.ID)
	}

	business_type := requestData.BusinessType

	ai_message := models.AIMessage{
		UserId:           user_id,
		Content:          userMessage,
		Type:             "user",
		AIConversationId: ai_conversation_id,
	}
	if err := tx.Create(&ai_message).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "新建消息失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}
	//安全培训
	if business_type == 1 {
		Prompt := models.Prompt{}
		models.DB.Model(&Prompt).Where("business_type = ? AND is_deleted = ?", business_type, 0).First(&Prompt)
		userMessage1 = Prompt.Prompt + userMessage
	}

	//AI写作
	if business_type == 2 {
		prompt := `# AI公文写作智能生成系统提示词

## 系统角色
你是一位精通中国政府和企业公文写作的专家，能够根据用户输入的信息智能识别文档类型，并生成格式规范、语言严谨的正式公文。你擅长撰写通知、公告、决定、会议纪要、工作总结等各类公文。

## 任务说明
1. 根据用户提供的信息，智能判断需要生成的公文类型
2. 基于识别的文档类型，采用相应的写作规范和格式要求
3. 对于用户未填写或填写错误的信息，进行合理推断或使用通用表述
4. 生成完整的公文内容

## 文档类型识别规则

### 1. 通知类
**识别关键词**：通知、开展、举办、培训、会议、活动、要求、部署
**适用场景**：传达事项、布置工作、告知信息

### 2. 公告类  
**识别关键词**：公告、公布、宣布、招标、采购、征集、声明
**适用场景**：向社会公众发布重要信息

### 3. 决定类
**识别关键词**：决定、表彰、奖励、任免、调整、废止、批准
**适用场景**：重大决策、人事任免、制度变更

### 4. 会议纪要类
**识别关键词**：会议、纪要、研究、审议、议定、讨论
**适用场景**：记录会议内容和决议事项

### 5. 工作总结类
**识别关键词**：总结、汇报、报告、回顾、成果、问题、计划
**适用场景**：阶段性工作回顾和未来规划

## 写作规范要求

### 通用格式要素
- **文号**：[单位简称]发〔年份〕XX号
- **标题**：居中，明确主题
- **主送机关**：明确接收单位
- **正文**：结构清晰，逻辑严密
- **落款**：发文单位和日期

### 语言风格要求
- 使用规范的公文语言
- 表述准确、简洁、庄重
- 避免口语化和情绪化表达
- 采用第三人称客观叙述

## 容错处理机制

### 信息缺失处理
- **发文单位缺失**：使用"[发文单位]"占位
- **时间信息缺失**：使用"[具体时间]"或当前时间
- **具体内容缺失**：使用"[具体内容]"占位并提示补充

### 信息错误处理
- **格式错误**：自动规范化处理
- **逻辑错误**：进行合理推断和调整
- **类型混淆**：基于关键词重新判断文档类型

### 信息冗余处理
- **重复信息**：去重并整合
- **无关信息**：筛选相关内容
- **格式混乱**：重新组织结构

## 具体写作模板

### 通知类模板
#### 写作要求
1.  **文号**：在文档最上方靠右的位置，格式为"[公司/部门简称]发[年份]XX号"。
2.  **标题**：居中，格式为"关于[通知主题]的通知"。
3.  **收文单位**：在标题下方，顶格写，明确通知的接收部门或人员，以冒号结尾。
4.  **正文**：
    *   **开头**：简明扼要地说明发文的背景、目的或依据。
    *   **主体**：采用分点、分条的方式，清晰列出通知的具体事项。至少应包含以下要素（根据实际情况增减）：
        *   一、[事项一名称]（例如：培训对象、活动范围）
        *   二、[事项二名称]（例如：时间安排、地点信息）
        *   三、[事项三名称]（例如：主要内容、工作要求）
        *   四、[事项四名称]（例如：组织单位、责任分工）
        *   五、[事项五名称]（例如：其他要求、注意事项）
    *   **结尾**：使用标准公文结束语，如"特此通知。"
5.  **落款**：
    *   在正文右下方，写明发文单位全称。
    *   在发文单位下方，写明完整的发文日期，格式为"XXXX年XX月XX日"。

#### 核心信息
- **发文单位**：[请填写发文单位全称]
- **发文年份**：[请填写年份]
- **通知主题**：[请填写通知的核心主题，例如"开展XX活动"]
- **收文单位**：[请填写需要接收此通知的部门或人员，多个单位用顿号隔开]
- **发文背景和目的**：[请简要说明为什么发这个通知]
- **具体事项**：
    1.  **事项一**：[请详细描述第一个事项]
    2.  **事项二**：[请详细描述第二个事项]
    3.  **事项三**：[请详细描述第三个事项]
    4.  ...（可根据需要增加更多事项）
- **发文日期**：[请填写发文日期]

### 公告类模板
#### 写作要求
1.  **标题结构**：
    *   第一行：发文单位全称，居中。
    *   第二行："公告"，居中。
    *   第三行："(第XX号)"，居中。
2.  **正文**：
    *   **开头**：简明扼要地说明发布此公告的背景、目的和依据（如相关法律法规）。
    *   **主体**：采用分点、分条的方式（一、二、三...），清晰列出公告的具体条款。内容应逻辑清晰，层层递进。
        *   一、[总则或基本原则]
        *   二、[具体规定或许可/禁止事项]
        *   三、[相关方的权利和义务]
        *   四、[执行和监督要求]
        *   五、[违反规定的处理措施或法律责任]
        *   六、[其他补充说明]
    *   **结尾**：无特定结尾套话，直接进入落款。
3.  **落款**：
    *   在正文右下方，写明发文单位全称。
    *   在发文单位下方，写明完整的发文日期，格式为"XXXX年XX月XX日"。
4.  **语言风格**：正式、权威、不容置疑，多使用"应"、"必须"、"严禁"等词语。

####  核心信息
- **发文单位**：[请填写发文单位全称]
- **公告编号**：[请填写公告的序号]
- **发布背景**：[请简要说明为何发布此公告，例如"为规范XX行为..."]
- **法律或政策依据**：[请列出相关的法律、法规或上级文件名称]
- **公告核心条款**：
    1.  **条款一**：[请详细描述第一个核心规定]
    2.  **条款二**：[请详细描述第二个核心规定]
    3.  **条款三**：[请详细描述第三个核心规定]
    4.  ...（可根据需要增加更多条款）
- **发文日期**：[请填写发文日期]

### 决定类模板
#### 写作要求
1.  **标题格式**：【发文单位】关于【具体决定事项】的决定
2.  **文号**：在标题下方居中标注文号，如"X府发〔2024〕XX号"或"X府令第XX号"
3.  **主送机关**：列明文件的主要接收单位
4.  **正文结构**：
    - **开头段落**：说明决定的背景、目的和依据
    - **决定主体**：明确宣告"经研究，决定如下："或"XX决定："
    - **具体内容**：详细阐述决定的具体事项，可分条列举或段落叙述
    - **执行要求**：对相关单位和人员提出明确要求
    - **生效条款**：说明决定的生效时间和适用范围
5.  **语言特点**：
    - 使用权威性、确定性的表述，如"决定"、"授予"、"废止"、"调整"等
    - 保持语言庄重严肃，体现公文的权威性
    - 表述准确清晰，避免模糊用词
6.  **附件**：如有详细名单、清单或补充材料，应在正文后附上
7.  **落款**：右下角署发文单位名称和发文日期

#### 核心信息
- **发文单位**：【请填写发文机关全称】
- **决定事项**：【请简要描述要决定的核心事项】
- **决定背景**：【请说明为什么要做出这个决定】
- **决定依据**：【请提供相关法律法规、政策文件或管理制度依据】
- **具体内容**：【请详细描述决定的具体内容，包括涉及的对象、标准、程序等】
- **执行要求**：【请说明对相关单位和人员的具体要求】
- **生效时间**：【请填写决定的生效日期】
- **主送机关**：【请列出主要接收单位】
- **附件信息**：【如有附件，请说明附件名称和主要内容】

### 会议纪要类模板
#### 写作要求
1.  **标题**：格式为"【会议名称】会议纪要"，下方标注会议日期，如"（2023年10月26日）"。
2.  **导语（第一段）**：清晰说明会议的基本要素，包括：
    *   **时间**：X月X日
    *   **主持人**：【职务】+【姓名】
    *   **会议名称**：主持召开【会议全称】
    *   **核心议题**：研究/部署/审议【核心事项】
    *   **参会人员**：【参会人员范围概述】参加会议。
    *   **会议流程**：会议听取了...汇报，审议了...文件，研究了...事项，并对下一步工作作出部署。
3.  **过渡段落（可选）**：根据需要，可以加入"会议认为"、"会议指出"、"会议强调"等段落，用于概括会议对当前形势的判断和对工作重要性的强调。
4.  **核心内容（议定事项）**：
    *   必须以"会议议定以下事项："作为起始句。
    *   采用分点（一、二、三...）的方式，清晰列出会议达成的共识和决策。
    *   每个议定事项都应包含"做什么（任务）、谁来做（责任单位）、怎么做（具体要求）、做到什么程度（目标）"等要素。
    *   事项标题应简明扼要，概括该项任务的核心。
5.  **结尾**：
    *   列出详细的"出席"人员名单，格式为"【单位】+【姓名】"。
    *   在文末右下角署发文单位和发文日期。
6.  **语言风格**：客观、准确、精炼、正式，采用第三人称叙述。

#### 核心信息
- **会议名称**：【请填写会议全称】
- **会议日期**：【请填写】
- **主持人**：【请填写职务和姓名】
- **主要议题**：【请概括会议讨论的核心议题】
- **会议背景/汇报内容**：【请简要说明会议听取了哪些汇报】
- **议定事项**：
    1.  **事项一标题**：【例如：加快推进XX项目建设】
        *   **具体内容**：【请详细描述该事项的任务、要求和目标】
        *   **责任单位**：【请明确牵头单位和配合单位】
    2.  **事项二标题**：【例如：强化XX领域安全监管】
        *   **具体内容**：【请详细描述】
        *   **责任单位**：【请明确】
    3.  ...（可根据需要增加更多事项）
- **出席人员名单**：【请按"单位+姓名"格式提供，用逗号隔开】
- **发文单位**：【例如：XX公司办公室】
- **发文日期**：【请填写】

### 工作总结类模板
#### 写作要求
1.  **标题**：格式为"【部门/个人名称】关于【时间范围，如：2023年度】工作总结及【下一阶段】工作计划的报告"。
2.  **结构**：严格遵循"总结过去、分析不足、展望未来"的三段式结构。
3.  **正文**：
    *   **开头**：简要概括总结期间的整体工作情况，点明核心业绩和总体评价。
    *   **第一部分：本阶段工作总结**
        *   采用分点（一、二、三...）或分领域的方式展开。
        *   每个要点都应包含"目标-行动-结果"的逻辑链条。
        *   尽可能使用量化数据来支撑业绩，例如完成率、增长率、具体数字等。
        *   示例要点：
            *   （一）核心业务指标完成情况：[列出关键KPI及其完成度]
            *   （二）重点项目推进成果：[描述关键项目的进展和成果]
            *   （三）团队建设与管理：[说明团队成长、培训、文化建设等]
            *   （四）流程优化与效率提升：[介绍在降本增效方面的举措和成效]
    *   **第二部分：存在的问题与不足**
        *   诚恳、客观地分析工作中存在的问题，不回避、不夸大。
        *   深入分析问题产生的根本原因，可以从内部（如技能、资源）和外部（如市场、政策）两个维度进行分析。
        *   示例要点：
            *   （一）[问题一]：[具体描述问题现象]，根本原因在于[分析原因]。
            *   （二）[问题二]：[具体描述问题现象]，根本原因在于[分析原因]。
    *   **第三部分：下一阶段工作计划**
        *   针对上一部分提出的问题，制定具体、可行的改进措施和工作计划。
        *   计划应具有SMART原则（具体、可衡量、可实现、相关、有时限）。
        *   示例要点：
            *   （一）[工作目标一]：为实现此目标，计划采取[具体措施]，预计在[时间点]完成，达成[可衡量的结果]。
            *   （二）[工作目标二]：...
4.  **语言风格**：专业、客观、简洁，避免口语化和情绪化表达。

#### 核心信息
- **总结主体**：【请填写部门或个人名称】
- **时间范围**：【例如：2023年1月1日 至 2023年12月31日】
- **核心业绩亮点**：
    1.  【业绩一】：【请用数据和事实简要描述】
    2.  【业绩二】：【请用数据和事实简要描述】
    3.  ...
- **存在的主要问题**：
    1.  【问题一】：【请简要描述】
    2.  【问题二】：【请简要描述】
- **下一阶段核心目标**：
    1.  【目标一】：【请简要描述】
    2.  【目标二】：【请简要描述】
- **报告日期**：【请填写报告撰写日期】

## 输出格式要求

请根据用户的问题或需求进行回复。

如果用户需要文档，请严格按照以下格式回复：

<OPENING_START>
以下是为您准备的文档，包含相关内容：
</OPENING_END>

<DOCUMENT_START>
[在这里生成完整的Word文档内容，必须包含：
1. 文档标题（使用#标记）
2. 多个章节（使用##标记）
3. 详细内容（使用Markdown格式，支持大小标题、换行、列表、加粗、斜体等富文本效果）
4. 确保内容完整，不要中途停止]
</DOCUMENT_END>

<CLOSING_START>
以上文档采用专业的格式编写，符合办公文档要求。如需调整内容或格式，请告诉我具体需求。
</CLOSING_END>

如果是普通问题，请直接回答，不要使用上述格式。

重要提醒：
1. 如果生成文档，必须包含三个标签区域：<OPENING_START>开头文本</OPENING_END>、<DOCUMENT_START>文档内容</DOCUMENT_END>、<CLOSING_START>结尾文本</CLOSING_END>
2. 确保每个区域都完整，特别是结尾部分不能缺失
3. 标签必须严格按照上述格式，不能有任何变化
4. 文档内容中不要使用emoji表情符号
5. 如果用户明确要求生成文档、报告、通知、方案等办公文档，必须使用上述格式
6. 标签名称区分大小写，必须完全匹配

示例正确格式：
<OPENING_START>
以下是为您准备的文档，包含相关内容：
</OPENING_END>

<DOCUMENT_START>
# 文档标题
## 第一章 概述
详细内容...
## 第二章 具体内容
详细内容...
</DOCUMENT_END>

<CLOSING_START>
以上文档采用专业的格式编写，符合办公文档要求。如需调整内容或格式，请告诉我具体需求。
</CLOSING_END>

## 处理流程
1. 接收用户输入的信息
2. 分析关键词，判断文档类型
3. 识别已提供的信息要素
4. 标记缺失或错误的信息
5. 基于模板生成完整公文
6. 按指定格式返回结果

现在请根据用户提供的信息生成相应的公文。
用户输入内容：` + userMessage + `
`

		userMessage1 = prompt
	}

	//如果是考试工坊则更新ai_conversation表中的content和exam_name
	if business_type == 3 {
		if err := tx.Model(&models.AIConversation{}).Where("id = ?", ai_conversation_id).Update("content", userMessage).Update("exam_name", requestData.ExamName).Error; err != nil {
			tx.Rollback()
			c.Data["json"] = map[string]interface{}{
				"statusCode": 500,
				"msg":        "更新内容失败: " + err.Error(),
			}
			c.ServeJSON()
			return
		}
	}
	var reply string
	var err error
	// 使用阿里大模型替代DeepSeek
	if business_type != 0 {
		reply, err = c.sendQwen3Message(userMessage1, false) // 使用流式响应
		if err != nil {
			tx.Rollback()
			c.Data["json"] = map[string]interface{}{
				"statusCode": 500,
				"msg":        "阿里大模型调用失败: " + err.Error(),
			}
			c.ServeJSON()
			return
		}
	} else {
		//这里写完成呃rag请求逻辑
		prompt := `# AI公文写作智能生成系统提示词

		## 系统角色
		你是一位精通中国政府和企业公文写作的专家，能够根据用户输入的信息智能识别文档类型，并生成格式规范、语言严谨的正式公文。你擅长撰写通知、公告、决定、会议纪要、工作总结等各类公文。
		
		## 任务说明
		1. 根据用户提供的信息，智能判断需要生成的公文类型
		2. 基于识别的文档类型，采用相应的写作规范和格式要求
		3. 对于用户未填写或填写错误的信息，进行合理推断或使用通用表述
		4. 生成完整的公文内容
		5. **生成后的内容严格按照格式要求返回**
		
		## 文档类型识别规则
		
		### 1. 通知类
		**识别关键词**：通知、开展、举办、培训、会议、活动、要求、部署
		**适用场景**：传达事项、布置工作、告知信息
		
		### 2. 公告类  
		**识别关键词**：公告、公布、宣布、招标、采购、征集、声明
		**适用场景**：向社会公众发布重要信息
		
		### 3. 决定类
		**识别关键词**：决定、表彰、奖励、任免、调整、废止、批准
		**适用场景**：重大决策、人事任免、制度变更
		
		### 4. 会议纪要类
		**识别关键词**：会议、纪要、研究、审议、议定、讨论
		**适用场景**：记录会议内容和决议事项
		
		### 5. 工作总结类
		**识别关键词**：总结、汇报、报告、回顾、成果、问题、计划
		**适用场景**：阶段性工作回顾和未来规划
		
		## 写作规范要求
		
		### 通用格式要素
		- **文号**：[单位简称]发〔年份〕XX号
		- **标题**：居中，明确主题
		- **主送机关**：明确接收单位
		- **正文**：结构清晰，逻辑严密
		- **落款**：发文单位和日期
		
		### 语言风格要求
		- 使用规范的公文语言
		- 表述准确、简洁、庄重
		- 避免口语化和情绪化表达
		- 采用第三人称客观叙述
		
		## 容错处理机制
		
		### 信息缺失处理
		- **发文单位缺失**：使用"[发文单位]"占位
		- **时间信息缺失**：使用"[具体时间]"或当前时间
		- **具体内容缺失**：使用"[具体内容]"占位并提示补充
		
		### 信息错误处理
		- **格式错误**：自动规范化处理
		- **逻辑错误**：进行合理推断和调整
		- **类型混淆**：基于关键词重新判断文档类型
		
		### 信息冗余处理
		- **重复信息**：去重并整合
		- **无关信息**：筛选相关内容
		- **格式混乱**：重新组织结构
		
		## 具体写作模板
		
		### 通知类模板
		#### 写作要求
		1.  **文号**：在文档最上方靠右的位置，格式为"[公司/部门简称]发[年份]XX号"。
		2.  **标题**：居中，格式为"关于[通知主题]的通知"。
		3.  **收文单位**：在标题下方，顶格写，明确通知的接收部门或人员，以冒号结尾。
		4.  **正文**：
			*   **开头**：简明扼要地说明发文的背景、目的或依据。
			*   **主体**：采用分点、分条的方式，清晰列出通知的具体事项。至少应包含以下要素（根据实际情况增减）：
				*   一、[事项一名称]（例如：培训对象、活动范围）
				*   二、[事项二名称]（例如：时间安排、地点信息）
				*   三、[事项三名称]（例如：主要内容、工作要求）
				*   四、[事项四名称]（例如：组织单位、责任分工）
				*   五、[事项五名称]（例如：其他要求、注意事项）
			*   **结尾**：使用标准公文结束语，如"特此通知。"
		5.  **落款**：
			*   在正文右下方，写明发文单位全称。
			*   在发文单位下方，写明完整的发文日期，格式为"XXXX年XX月XX日"。
		
		#### 核心信息
		- **发文单位**：[请填写发文单位全称]
		- **发文年份**：[请填写年份]
		- **通知主题**：[请填写通知的核心主题，例如"开展XX活动"]
		- **收文单位**：[请填写需要接收此通知的部门或人员，多个单位用顿号隔开]
		- **发文背景和目的**：[请简要说明为什么发这个通知]
		- **具体事项**：
			1.  **事项一**：[请详细描述第一个事项]
			2.  **事项二**：[请详细描述第二个事项]
			3.  **事项三**：[请详细描述第三个事项]
			4.  ...（可根据需要增加更多事项）
		- **发文日期**：[请填写发文日期]
		
		### 公告类模板
		#### 写作要求
		1.  **标题结构**：
			*   第一行：发文单位全称，居中。
			*   第二行："公告"，居中。
			*   第三行："(第XX号)"，居中。
		2.  **正文**：
			*   **开头**：简明扼要地说明发布此公告的背景、目的和依据（如相关法律法规）。
			*   **主体**：采用分点、分条的方式（一、二、三...），清晰列出公告的具体条款。内容应逻辑清晰，层层递进。
				*   一、[总则或基本原则]
				*   二、[具体规定或许可/禁止事项]
				*   三、[相关方的权利和义务]
				*   四、[执行和监督要求]
				*   五、[违反规定的处理措施或法律责任]
				*   六、[其他补充说明]
			*   **结尾**：无特定结尾套话，直接进入落款。
		3.  **落款**：
			*   在正文右下方，写明发文单位全称。
			*   在发文单位下方，写明完整的发文日期，格式为"XXXX年XX月XX日"。
		4.  **语言风格**：正式、权威、不容置疑，多使用"应"、"必须"、"严禁"等词语。
		
		####  核心信息
		- **发文单位**：[请填写发文单位全称]
		- **公告编号**：[请填写公告的序号]
		- **发布背景**：[请简要说明为何发布此公告，例如"为规范XX行为..."]
		- **法律或政策依据**：[请列出相关的法律、法规或上级文件名称]
		- **公告核心条款**：
			1.  **条款一**：[请详细描述第一个核心规定]
			2.  **条款二**：[请详细描述第二个核心规定]
			3.  **条款三**：[请详细描述第三个核心规定]
			4.  ...（可根据需要增加更多条款）
		- **发文日期**：[请填写发文日期]
		
		### 决定类模板
		#### 写作要求
		1.  **标题格式**：【发文单位】关于【具体决定事项】的决定
		2.  **文号**：在标题下方居中标注文号，如"X府发〔2024〕XX号"或"X府令第XX号"
		3.  **主送机关**：列明文件的主要接收单位
		4.  **正文结构**：
			- **开头段落**：说明决定的背景、目的和依据
			- **决定主体**：明确宣告"经研究，决定如下："或"XX决定："
			- **具体内容**：详细阐述决定的具体事项，可分条列举或段落叙述
			- **执行要求**：对相关单位和人员提出明确要求
			- **生效条款**：说明决定的生效时间和适用范围
		5.  **语言特点**：
			- 使用权威性、确定性的表述，如"决定"、"授予"、"废止"、"调整"等
			- 保持语言庄重严肃，体现公文的权威性
			- 表述准确清晰，避免模糊用词
		6.  **附件**：如有详细名单、清单或补充材料，应在正文后附上
		7.  **落款**：右下角署发文单位名称和发文日期
		
		#### 核心信息
		- **发文单位**：【请填写发文机关全称】
		- **决定事项**：【请简要描述要决定的核心事项】
		- **决定背景**：【请说明为什么要做出这个决定】
		- **决定依据**：【请提供相关法律法规、政策文件或管理制度依据】
		- **具体内容**：【请详细描述决定的具体内容，包括涉及的对象、标准、程序等】
		- **执行要求**：【请说明对相关单位和人员的具体要求】
		- **生效时间**：【请填写决定的生效日期】
		- **主送机关**：【请列出主要接收单位】
		- **附件信息**：【如有附件，请说明附件名称和主要内容】
		
		### 会议纪要类模板
		#### 写作要求
		1.  **标题**：格式为"【会议名称】会议纪要"，下方标注会议日期，如"（2023年10月26日）"。
		2.  **导语（第一段）**：清晰说明会议的基本要素，包括：
			*   **时间**：X月X日
			*   **主持人**：【职务】+【姓名】
			*   **会议名称**：主持召开【会议全称】
			*   **核心议题**：研究/部署/审议【核心事项】
			*   **参会人员**：【参会人员范围概述】参加会议。
			*   **会议流程**：会议听取了...汇报，审议了...文件，研究了...事项，并对下一步工作作出部署。
		3.  **过渡段落（可选）**：根据需要，可以加入"会议认为"、"会议指出"、"会议强调"等段落，用于概括会议对当前形势的判断和对工作重要性的强调。
		4.  **核心内容（议定事项）**：
			*   必须以"会议议定以下事项："作为起始句。
			*   采用分点（一、二、三...）的方式，清晰列出会议达成的共识和决策。
			*   每个议定事项都应包含"做什么（任务）、谁来做（责任单位）、怎么做（具体要求）、做到什么程度（目标）"等要素。
			*   事项标题应简明扼要，概括该项任务的核心。
		5.  **结尾**：
			*   列出详细的"出席"人员名单，格式为"【单位】+【姓名】"。
			*   在文末右下角署发文单位和发文日期。
		6.  **语言风格**：客观、准确、精炼、正式，采用第三人称叙述。
		
		#### 核心信息
		- **会议名称**：【请填写会议全称】
		- **会议日期**：【请填写】
		- **主持人**：【请填写职务和姓名】
		- **主要议题**：【请概括会议讨论的核心议题】
		- **会议背景/汇报内容**：【请简要说明会议听取了哪些汇报】
		- **议定事项**：
			1.  **事项一标题**：【例如：加快推进XX项目建设】
				*   **具体内容**：【请详细描述该事项的任务、要求和目标】
				*   **责任单位**：【请明确牵头单位和配合单位】
			2.  **事项二标题**：【例如：强化XX领域安全监管】
				*   **具体内容**：【请详细描述】
				*   **责任单位**：【请明确】
			3.  ...（可根据需要增加更多事项）
		- **出席人员名单**：【请按"单位+姓名"格式提供，用逗号隔开】
		- **发文单位**：【例如：XX公司办公室】
		- **发文日期**：【请填写】
		
		### 工作总结类模板
		#### 写作要求
		1.  **标题**：格式为"【部门/个人名称】关于【时间范围，如：2023年度】工作总结及【下一阶段】工作计划的报告"。
		2.  **结构**：严格遵循"总结过去、分析不足、展望未来"的三段式结构。
		3.  **正文**：
			*   **开头**：简要概括总结期间的整体工作情况，点明核心业绩和总体评价。
			*   **第一部分：本阶段工作总结**
				*   采用分点（一、二、三...）或分领域的方式展开。
				*   每个要点都应包含"目标-行动-结果"的逻辑链条。
				*   尽可能使用量化数据来支撑业绩，例如完成率、增长率、具体数字等。
				*   示例要点：
					*   （一）核心业务指标完成情况：[列出关键KPI及其完成度]
					*   （二）重点项目推进成果：[描述关键项目的进展和成果]
					*   （三）团队建设与管理：[说明团队成长、培训、文化建设等]
					*   （四）流程优化与效率提升：[介绍在降本增效方面的举措和成效]
			*   **第二部分：存在的问题与不足**
				*   诚恳、客观地分析工作中存在的问题，不回避、不夸大。
				*   深入分析问题产生的根本原因，可以从内部（如技能、资源）和外部（如市场、政策）两个维度进行分析。
				*   示例要点：
					*   （一）[问题一]：[具体描述问题现象]，根本原因在于[分析原因]。
					*   （二）[问题二]：[具体描述问题现象]，根本原因在于[分析原因]。
			*   **第三部分：下一阶段工作计划**
				*   针对上一部分提出的问题，制定具体、可行的改进措施和工作计划。
				*   计划应具有SMART原则（具体、可衡量、可实现、相关、有时限）。
				*   示例要点：
					*   （一）[工作目标一]：为实现此目标，计划采取[具体措施]，预计在[时间点]完成，达成[可衡量的结果]。
					*   （二）[工作目标二]：...
		4.  **语言风格**：专业、客观、简洁，避免口语化和情绪化表达。
		
		#### 核心信息
		- **总结主体**：【请填写部门或个人名称】
		- **时间范围**：【例如：2023年1月1日 至 2023年12月31日】
		- **核心业绩亮点**：
			1.  【业绩一】：【请用数据和事实简要描述】
			2.  【业绩二】：【请用数据和事实简要描述】
			3.  ...
		- **存在的主要问题**：
			1.  【问题一】：【请简要描述】
			2.  【问题二】：【请简要描述】
		- **下一阶段核心目标**：
			1.  【目标一】：【请简要描述】
			2.  【目标二】：【请简要描述】
		- **报告日期**：【请填写报告撰写日期】
		
		## 输出格式要求
		
		请根据用户的问题或需求进行回复，如果用户需要文档，请严格按照以下格式回复：
		
		“
		<OPENING_START>
		以下是为您准备的文档，包含相关内容：
		</OPENING_END>
		
		<DOCUMENT_START>
		[在这里生成完整的Word文档内容，必须包含：
		1. 文档标题（使用#标记）
		2. 多个章节（使用##标记）
		3. 详细内容（使用Markdown格式，支持大小标题、换行、列表、加粗、斜体等富文本效果）
		4. 确保内容完整，不要中途停止]
		</DOCUMENT_END>
		
		<CLOSING_START>
		以上文档采用专业的格式编写，符合办公文档要求。如需调整内容或格式，请告诉我具体需求。
		</CLOSING_END>
		
		”
		
		##示例正确格式：
		<OPENING_START>
		以下是为您准备的文档，包含相关内容：
		</OPENING_END>
		
		<DOCUMENT_START>
		# 文档标题
		## 第一章 概述
		详细内容...
		## 第二章 具体内容
		详细内容...
		</DOCUMENT_END>
		
		<CLOSING_START>
		以上文档采用专业的格式编写，符合办公文档要求。如需调整内容或格式，请告诉我具体需求。
		</CLOSING_END>
		
		
		
		## 重要提醒：
		1. 如果生成文档，返回的结果必须包含三个标签区域：<OPENING_START>开头文本</OPENING_END>、<DOCUMENT_START>文档内容</DOCUMENT_END>、<CLOSING_START>结尾文本</CLOSING_END>
		2. 确保每个区域都完整，特别是结尾部分不能缺失
		3. 标签必须严格按照上述格式，不能有任何变化
		4. 文档内容中不要使用emoji表情符号
		5. 如果用户明确要求生成会议纪要、通知、决定、公告、总结报告的办公文档，必须使用上述格式
		6. 标签名称区分大小写，必须完全匹配
		7.如果是普通问题，请直接回答，不要使用上述格式。
		
		
		## 处理流程
		1. 接收用户输入的信息
		2. 分析关键词，判断文档类型
		3. 识别已提供的信息要素
		4. 标记缺失或错误的信息
		5. 基于模板生成完整公文
		6. 按指定格式返回结果
		
		现在请根据用户提供的信息生成相应的公文。
		用户输入内容：` + userMessage + `
		`

		reply, err = c.sendQwen3Message(prompt, false) // 使用流式响应
		if err != nil {
			tx.Rollback()
			c.Data["json"] = map[string]interface{}{
				"statusCode": 500,
				"msg":        "阿里大模型调用失败: " + err.Error(),
			}
			c.ServeJSON()
			return
		}
		fmt.Println("reply:", reply)

		// 解析AI返回的JSON响应
		var aiResponse map[string]interface{}
		// 清理回复中的换行符和多余空白字符
		cleanReply := strings.TrimSpace(reply)
		// 移除可能的markdown代码块标记
		cleanReply = strings.TrimPrefix(cleanReply, "```json")
		cleanReply = strings.TrimSuffix(cleanReply, "```")
		cleanReply = strings.TrimSpace(cleanReply)

		if err := json.Unmarshal([]byte(cleanReply), &aiResponse); err != nil {
			// 如果解析失败，记录错误并返回默认回复
			fmt.Printf("JSON解析失败，原始回复: %s\n", reply)
			fmt.Printf("清理后回复: %s\n", cleanReply)
			fmt.Printf("解析错误: %v\n", err)
			reply = "抱歉，我暂时无法理解您的问题，请尝试重新表述。"
		} else {
			intent, ok := aiResponse["intent"].(string)
			if !ok {
				reply = "解析失败2"
			} else {
				// 根据intent类型决定返回内容
				if intent == "greeting" || intent == "faq" || intent == "out_of_scope" {
					if directAnswer, exists := aiResponse["direct_answer"].(string); exists && directAnswer != "" {
						reply = directAnswer
					} else {
						reply = "解析失败3"
					}
				} else {
					// reply = "复杂问题，进入下一步"
					//取出里面的数组search_queries
					search_queries, ok := aiResponse["search_queries"].([]interface{})
					if !ok || len(search_queries) == 0 {
						reply = "解析失败4"
					} else {
						// 将search_queries转换为字符串数组
						var queries []string
						for _, query := range search_queries {
							if queryStr, ok := query.(string); ok {
								queries = append(queries, queryStr)
							}
						}

						// 使用第一个查询进行搜索
						if len(queries) > 0 {
							// 构建搜索请求
							searchRequest := map[string]interface{}{
								"query":     queries[0], // 使用第一个查询
								"n_results": 10,         // 返回3个结果
							}

							requestBody, err := json.Marshal(searchRequest)
							if err != nil {
								reply = "解析失败5"
							} else {
								// 从配置文件中读取搜索API地址
								searchAPIURL, err := web.AppConfig.String("search_api_url")
								if err != nil || searchAPIURL == "" {
									reply = "配置文件中未找到search_api_url"
								} else {
									// 发送HTTP请求到本地Python服务
									req, err := http.NewRequest("POST", searchAPIURL, bytes.NewBuffer(requestBody))
									if err != nil {
										reply = "解析失败6"
									} else {
										req.Header.Set("Content-Type", "application/json")

										client := &http.Client{Timeout: 30 * time.Second}
										resp, err := client.Do(req)
										if err != nil {
											reply = "解析失败7"
										} else {
											defer resp.Body.Close()

											responseBody, err := io.ReadAll(resp.Body)
											if err != nil {
												reply = "解析失败8"
											} else if resp.StatusCode != http.StatusOK {
												reply = "解析失败9"
											} else {
												// 解析搜索响应
												var searchResponse map[string]interface{}
												if err := json.Unmarshal(responseBody, &searchResponse); err != nil {
													reply = "解析失败10"
												} else {
													// 检查响应状态
													fmt.Println("searchResponse11111111:", searchResponse)
													status, ok := searchResponse["status"].(string)
													if !ok || status != "success" {
														message, _ := searchResponse["message"].(string)
														reply = fmt.Sprintf("搜索失败: %s", message)
													} else {
														// 获取搜索结果
														results, ok := searchResponse["results"].([]interface{})
														// fmt.Println("results:", results)
														if !ok || len(results) == 0 {
															reply = "未找到相关文档"
														} else {
															// 直接将原始搜索结果转换为JSON字符串作为上下文
															contextJSON, err := json.Marshal(results)
															if err != nil {
																reply = "处理搜索结果失败: " + err.Error()
															} else {
																// 构建新的JSON格式提示词
																finalPrompt := `# Role
你是一名专业的"蜀道AI安全助手"智能问答助手，专注于提供路桥隧轨等基建建筑施工技术相关的专业咨询服务。

# Overall Goal
你的核心任务是根据用户问题<question>和检索到的上下文<context>，生成一个包含自然语言回答和结构化数据的JSON对象。你需要精准地处理"国家规范"、"标准规范"、"集团规范"三类查询，并为所有信息提供清晰、可追溯的来源。


# Core Task Workflow
1. **Analyze & Filter Context**: 评估<context>中每个文档与<question>的相关性，筛选出"高度相关"的文档用于生成答案。
2. **Construct JSON Output**: 严格按照Final Output JSON Structure构建最终的JSON对象，确保所有字段都正确填充。


# Step-by-Step Instructions

## 1. Context Analysis & Filtering
- **High-Relevance Criteria**: 一份文档被视为"高度相关"，必须同时满足以下条件：
  - 文档的标题、章节标题或内容直接回应了用户<question>的核心意图。
  - 文档的关键词与<question>中的关键术语有高度重叠。
- **Filtering**: 丢弃所有不满足"高度相关"的文档。如果筛选后没有剩下任何文档，则直接跳转到Edge Case Handling中的"信息不足"场景。

## 2. Answer Synthesis (Response Format Rules)
- **Dimension Mapping**: 将所有高度相关的文档根据其发布主体和内容分配到三个维度：
  - **national_level**: 国家和行业规范 (包含国家标准GB/T、行业标准JT/T, JGJ, CJJ等)。
  - **local_level**: 地方规范 (包含DB，通常是由省、市、区县等地方政府或其部门发布的文件，文件名通常包含地名)。
  - **enterprise_level**: 集团规范 (企业内部制定的制度、办法和规定，文件名通常包含公司名称)。
  
 
- **Natural Language Answer (natural_language_answer)**: 
  1. 以 "**您好，关于您的问题，蜀道AI安全助手为您查询结果如下：**\n\n**问题描述：**\n[用户原始问题]\n\n**查询结果：**\n\n" 开头。
  2. 依次构建每个维度的回答，格式如下：
     - "1. **国家规范**\n[此处是国家或行业层面内容的自然语言表述，在文中自然地包含标准编号] [《文档名称》]\n\n"
     - "2. **地方规范**\n[此处是地方层面内容的自然语言表述] [《文档名称》]\n\n"
     - "3. **企业规范**\n[此处是企业层面内容的自然语言表述] [《文档名称》]\n\n"
  3. 对于没有检索到内容的维度，使用固定文本："根据现有资料，暂未检索到相关[维度名称]层面标准规范信息。建议参考：[基于真实知识的简要建议，不超过100字]"
- **Structured Data (structured_data)**: 
  - 为每个维度（national_level, local_level, enterprise_level）填充content和sources字段。
  - content: 该维度回答的纯文本内容（不含溯源标记）。
  - sources: 该维度使用的所有来源信息，格式为 "文档名称（标准编号，如有）"。去除重复项。
  



# Strict Rules & Edge Case Handling
1. **100% Context-Based**: 严禁回答<context>中未包含的任何信息。所有回答必须基于筛选出的"高度相关"文档。
2. **Source Tagging Format**: 溯源信息必须使用[《文档名称》]格式，放在每个维度内容的末尾。
3. **Standard Number Integration**: 标准编号应该自然地融入到正文内容中，而不是单独标注。
4. **Handling Insufficient Information**: 如果在过滤后没有任何"高度相关"的文档，必须返回以下JSON：
   {
     "answer_type": "no_answer",
     "natural_language_answer": "根据现有资料，无法找到与您问题高度相关的信息。建议您尝试更换关键词或调整提问方式。",
     "structured_data": {},
     "metadata": {"total_sources": 0}
   }
5. **Content Filtering**: 如果<context>中的内容包含疑似乱码、表格代码或公式，不要直接输出，而是用 "（内容包含公式、表格或图片特殊格式，请前往原文档查看）" 代替，并正常标注来源。
6. **JSON Validity**: 确保最终输出是单个、完整且格式正确的JSON对象。所有字符串内的换行符必须转义为\\n。



# Final Output JSON Structure
你必须严格输出以下JSON格式。不要在JSON前后添加任何额外文本或解释。

{
  "answer_type": [
    "standard",
    "no_answer"
  ],
  "natural_language_answer": "(string) 按照上述格式要求生成的完整回答文本，包含问题描述和查询结果部分。",
  "structured_data": {
    "national_level": {
      "content": "(string) 国家规范相关内容的纯文本表述。",
      "sources": [
        "(string) 文档名称1（标准编号1）",
        "(string) 文档名称2（标准编号2）"
      ]
    },
    "local_level": {
      "content": "(string) 地方规范相关内容的纯文本表述。",
      "sources": [
        "(string) 文档名称4（标准编号4）"
      ]
    },
    "enterprise_level": {
      "content": "(string) 企业规范相关内容的纯文本表述。",
      "sources": [
        "(string) 文档名称5（标准编号5）"
      ]
    }
  }
}


# Example Output (标准规范类)
{
  "structured_data": {
    "national_level": {
      "content": "根据《公路隧道施工门禁系统技术要求》（JT/T 1496-2024）第6章\"硬件技术要求\"规定，系统硬件应满足安全性、可靠性、先进性、可扩展性、开放性和实时性要求，所用设备应采用主流技术和通用产品，并符合国家或行业相关技术标准规范，经国家有关部门和监测检验机构认证、检验合格。",
      "sources": [
        "高速公路收费车道设备技术要求（JT/T 1496-2024）"
      ]
    },
    "local_level": {
      "content": "根据现有资料，暂未检索到相关地方层面标准规范信息。建议参考：结合项目所在地交通主管部门发布的隧道施工安全管理规定，补充地方性技术要求。",
      "sources": []
    },
    "enterprise_level": {
      "content": "根据现有资料，暂未检索到相关企业层面标准规范信息。建议参考：企业可依据《蜀道集团关于公路隧道施工技术要求》及项目实际需求，制定内部技术实施与验收细则，强化系统运维与数据管理。",
      "sources": []
    }
  },
  "metadata": {
    "total_sources": 1,
    "primary_document": "高速公路收费车道设备技术要求"
  }
}



# --- Execution Start ---

# Context
<context>
` + string(contextJSON) + `
</context>

# Question
<question>
` + userMessage + `
</question>

# Answer
请开始你的回答，严格遵循上述JSON格式：
`

																// 发送给千问模型进行最终回答
																finalReply, err := c.sendQwen3Message(finalPrompt, false) // 使用流式响应
																if err != nil {
																	reply = "生成最终回答失败: " + err.Error()
																} else {
																	// 解析AI返回的JSON响应
																	fmt.Printf("AI原始回复长度: %d\n", len(finalReply))
																	if len(finalReply) > 200 {
																		fmt.Printf("AI原始回复前200字符: %s\n", finalReply[:200])
																	} else {
																		fmt.Printf("AI原始回复: %s\n", finalReply)
																	}

																	// 尝试清理JSON字符串
																	cleanedReply := strings.TrimSpace(finalReply)
																	// 移除可能的markdown代码块标记
																	cleanedReply = strings.TrimPrefix(cleanedReply, "```json")
																	cleanedReply = strings.TrimPrefix(cleanedReply, "```")
																	cleanedReply = strings.TrimSuffix(cleanedReply, "```")
																	cleanedReply = strings.TrimSpace(cleanedReply)

																	var aiResponse map[string]interface{}
																	if err := json.Unmarshal([]byte(cleanedReply), &aiResponse); err != nil {
																		// 如果解析失败，尝试提取natural_language_answer字段的正则表达式
																		fmt.Printf("JSON解析失败，尝试正则提取: %v\n", err)
																		if strings.Contains(finalReply, "natural_language_answer") {
																			// 使用正则表达式提取natural_language_answer的内容
																			re := regexp.MustCompile(`"natural_language_answer"\s*:\s*"([^"]*(?:\\.[^"]*)*)"`)
																			matches := re.FindStringSubmatch(finalReply)
																			if len(matches) > 1 {
																				naturalAnswer := matches[1]
																				// 处理转义字符
																				naturalAnswer = strings.ReplaceAll(naturalAnswer, "\\n", "\n")
																				naturalAnswer = strings.ReplaceAll(naturalAnswer, "\\\"", "\"")
																				fmt.Printf("正则提取成功，长度: %d\n", len(naturalAnswer))
																				reply = naturalAnswer
																			} else {
																				fmt.Printf("正则提取失败，使用原始回复\n")
																				reply = finalReply
																			}
																		} else {
																			fmt.Printf("未找到natural_language_answer字段，使用原始回复\n")
																			reply = finalReply
																		}
																	} else {
																		// 提取natural_language_answer字段
																		if naturalAnswer, ok := aiResponse["natural_language_answer"].(string); ok {
																			fmt.Printf("成功提取natural_language_answer，长度: %d\n", len(naturalAnswer))
																			reply = naturalAnswer
																		} else {
																			// 如果字段不存在，使用原始回复
																			fmt.Printf("natural_language_answer字段不存在或类型错误\n")
																			reply = finalReply
																		}
																	}
																}
															}
														}
													}
												}
											}
										}
									}
								}
							}
						} else {
							reply = "未找到有效的查询内容"
						}
					}
				}
			}
		}
	}

	//新建AI回复
	ai_reply := models.AIMessage{
		UserId:           user_id,
		Content:          reply,
		Type:             "ai",
		AIConversationId: ai_conversation_id,
		PrevUserId:       uint64(ai_message.ID),
	}
	if err := tx.Create(&ai_reply).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "新建消息失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}
	//更新AIConversation编辑时间
	if err := tx.Model(&models.AIConversation{}).Where("id = ?", ai_conversation_id).Update("updated_at", time.Now().Unix()).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "更新编辑时间失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	tx.Commit()
	// 返回成功响应（保持与原来相同的格式）
	fmt.Printf("最终返回的reply内容长度: %d\n", len(reply))
	if len(reply) > 100 {
		fmt.Printf("最终返回的reply前100字符: %s\n", reply[:100])
	} else {
		fmt.Printf("最终返回的reply内容: %s\n", reply)
	}
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
		"data": map[string]interface{}{
			"reply": reply,
			// "user_message": userMessage,
			"ai_conversation_id": ai_conversation_id,
			"ai_message_id":      ai_reply.ID,
		},
	}
	c.ServeJSON()
}

// 删除对话
type DeleteConversationRequest struct {
	AIConversationID uint64 `json:"ai_conversation_id"`
	AIMessageID      uint64 `json:"ai_message_id"`
}

func (c *ChatController) DeleteConversation() {
	var requestData DeleteConversationRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	ai_message_id := requestData.AIMessageID
	fmt.Println("ai_message_id:", ai_message_id)
	tx := models.DB.Begin()
	//这里除了要删除这条ai消息，还要查询到prev_user_id这条消息，并删除
	if err := tx.Model(&models.AIMessage{}).Where("id = ?", ai_message_id).Update("is_deleted", 1).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "删除消息失败",
		}
		c.ServeJSON()
		return
	}
	var ai_message_user models.AIMessage
	models.DB.Where("id = ?", ai_message_id).First(&ai_message_user)
	prev_user_id := ai_message_user.PrevUserId
	if err := tx.Model(&models.AIMessage{}).Where("id = ?", prev_user_id).Update("is_deleted", 1).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "删除消息失败",
		}
		c.ServeJSON()
		return
	}

	//更新ai_conversation表中的编辑时间
	ai_conversation_id := ai_message_user.AIConversationId
	if err := tx.Model(&models.AIConversation{}).Where("id = ?", ai_conversation_id).Update("updated_at", time.Now().Unix()).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "更新编辑时间失败",
		}
		c.ServeJSON()
		return
	}
	tx.Commit()
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
	}
	c.ServeJSON()
}

// ppt大纲存主表
type SavePPTOutlineRequest struct {
	AIConversationID uint64 `json:"ai_conversation_id"`
	PPTOutline       string `json:"ppt_outline"`
}

func (c *ChatController) SavePPTOutline() {
	var requestData SavePPTOutlineRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	ai_conversation_id := requestData.AIConversationID
	ppt_outline := requestData.PPTOutline
	tx := models.DB.Begin()
	if err := tx.Model(&models.AIConversation{}).Where("id = ?", ai_conversation_id).Update("ppt_outline", ppt_outline).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "保存ppt大纲失败",
		}
	}
	tx.Commit()
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
	}
	c.ServeJSON()
}

// 返回历史记录
func (c *ChatController) GetHistoryRecord() {
	user_id, _ := c.GetInt64("user_id")
	ai_conversation_id, _ := c.GetInt64("ai_conversation_id")
	business_type, _ := c.GetInt64("business_type")
	if user_id == 0 {
		user_id = 1
	}
	//返回详情
	if ai_conversation_id > 0 {
		var ppt_outline string
		var ppt_json_content string
		//如果是ppt
		if business_type == 1 {
			var ai_conversation models.AIConversation
			models.DB.Model(&models.AIConversation{}).Where("id = ?", ai_conversation_id).First(&ai_conversation)
			ppt_outline = ai_conversation.PPTOutline
			ppt_json_content = ai_conversation.PPTJsonContent
		}

		var ai_message []models.AIMessage
		models.DB.Model(&models.AIMessage{}).Where("user_id = ? AND ai_conversation_id = ? AND is_deleted = ?", user_id, ai_conversation_id, 0).Order("updated_at").Find(&ai_message)
		c.Data["json"] = map[string]interface{}{
			"statusCode":       200,
			"msg":              "success",
			"data":             ai_message,
			"ppt_outline":      ppt_outline,
			"ppt_json_content": ppt_json_content,
		}
		fmt.Println("ppt_outline", ppt_outline)
		c.ServeJSON()
		return
	}

	// 检查数据库连接
	sqlDB, err := models.DB.DB()
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "数据库连接失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 测试数据库连接
	if err := sqlDB.Ping(); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "数据库连接测试失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	var ai_conversation []models.AIConversation
	models.DB.Model(&models.AIConversation{}).Where("user_id = ? AND is_deleted = ? AND business_type = ?", user_id, 0, business_type).Order("-updated_at").Find(&ai_conversation)

	//计算返回的总共的数据数量
	var total int64
	models.DB.Model(&models.AIConversation{}).Where("user_id = ? AND is_deleted = ? AND business_type = ?", user_id, 0, business_type).Count(&total)
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
		"data":       ai_conversation,
		"total":      total,
	}
	c.ServeJSON()
}

// 点赞和点踩post请求
func (c *ChatController) LikeAndDislike() {
	var requestData models.AIMessage
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	id := requestData.ID
	user_feedback := requestData.UserFeedback
	tx := models.DB.Begin()
	if err := tx.Model(&models.AIMessage{}).Where("id = ?", id).Update("user_feedback", user_feedback).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "点赞和点踩失败",
		}
		c.ServeJSON()
		return
	}
	tx.Commit()
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
	}
	c.ServeJSON()
}

// 直接问问题
func (c *ChatController) ReProduceSingleQuestion() {
	// 从请求体获取消息
	var requestData SendDeepSeekMessageRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	fmt.Println("请求数据:", requestData)

	userMessage := requestData.Message

	// 使用阿里大模型替代DeepSeek
	reply, err := c.sendQwen3Message(userMessage, false) // 使用流式响应
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "阿里大模型调用失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 返回成功响应（保持与原来相同的格式）
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
		"data": map[string]interface{}{
			"reply": reply,
		},
	}
	c.ServeJSON()
}

// 用户在输入框中每输入一个字，就调用一次阿里大模型返回推荐问题
func (c *ChatController) GetUserRecommendQuestion() {
	user_id, _ := c.GetInt64("user_id")
	if user_id == 0 {
		user_id = 1
	}
	userMessage := c.GetString("user_message")

	// 构建推荐问题的提示词
	prompt := `# Role
你是"蜀道AI"的智能问答向导。你的唯一任务是根据用户输入的关键词，生成一系列**必须查询国家标准（GB）、行业标准（JTG/TB等）、企业标准（QB）或公司内部制度文件才能回答**的专业问题。

## 知识库背景
请牢记，你能依赖的知识库主要由以下两类文档构成：
1.  **标准规范类**：包含海量的国标（GB）、行标（JTG/TB/QB等）、地标及其它专业标准规范。
2.  **办公制度类**：包含公司的各项内部管理制度、规定、办法、流程等文件。

## 任务与规则
请针对用户输入的关键词"` + userMessage + `"，生成5个推荐问题。规则极其严格：
1.  **格式强制**：每个问题**必须**以"` + userMessage + `"开头。
2.  **内容强制**：每个问题**必须**是对一个**具体标准条款**或**具体制度条文**的查询。
3.  **生成策略**：请使用以下模板来构思问题：
    - **对于标准类**："` + userMessage + `的[某项技术要求]应遵循哪本规范的哪一条款？"、"标准中对` + userMessage + `的[某项性能指标]是如何规定的？"
    - **对于制度类**："公司制度中关于` + userMessage + `的审批流程是怎样的？"、"` + userMessage + `的报销标准依据哪项内部规定？"
4.  **鼓励包含**：强烈建议在问题中直接包含"标准"、"规范"、"规定"、"制度"、"流程"、"条款"、"第几条"等词汇。
5.  **禁止生成**：禁止生成常识性问题、解释性问题和在知识库中肯定找不到答案的问题（如学术理论、就业前景、大学排名等）。

## 用户输入
"` + userMessage + `"

## 你的输出（直接生成问题列表，每行一个）`

	reply, err := c.sendQwen3Message(prompt, false) // 使用流式响应
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "阿里大模型调用失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 将回复按行分割成推荐问题列表
	questions := strings.Split(strings.TrimSpace(reply), "\n")
	var cleanQuestions []string
	for _, q := range questions {
		q = strings.TrimSpace(q)
		if q != "" {
			cleanQuestions = append(cleanQuestions, q)
		}
	}

	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
		"data": map[string]interface{}{
			"questions": cleanQuestions,
		},
	}
	c.ServeJSON()
}

// 用户传文件名取数据库寻找链接（使用编辑距离算法匹配最相似的文件名）
func (c *ChatController) GetFileLink() {
	fileName := c.GetString("fileName")
	fmt.Println("查询文件名:", fileName)

	// 获取所有未删除的文件记录
	var indexFiles []models.IndexFile
	models.DB.Model(&models.IndexFile{}).Where("is_deleted = ?", 0).Find(&indexFiles)

	if len(indexFiles) == 0 {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 404,
			"msg":        "数据库中没有找到任何文件",
			"data":       "",
		}
		c.ServeJSON()
		return
	}

	// 提取所有文件名作为候选列表
	var candidates []string
	for _, file := range indexFiles {
		candidates = append(candidates, file.FileName)
	}

	// 使用编辑距离算法找到最相似的文件名
	bestMatch, bestScore := utils.FindBestMatch(fileName, candidates)
	fmt.Printf("最佳匹配: %s (相似度: %.3f)\n", bestMatch, bestScore)

	// 找到对应的文件记录
	var matchedFile models.IndexFile
	for _, file := range indexFiles {
		if file.FileName == bestMatch {
			matchedFile = file
			break
		}
	}

	fmt.Println("匹配的文件记录:", matchedFile)
	fmt.Println("文件链接:", matchedFile.FilePath)

	// 如果相似度太低，可以设置阈值
	threshold := 0.3 // 相似度阈值，可以根据需要调整
	if bestScore < threshold {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 200,
			"msg":        fmt.Sprintf("没有找到相似度 >= %.1f 的文件，最佳匹配相似度: %.3f", threshold, bestScore),
			"data":       "",
			"bestMatch":  bestMatch,
			"bestScore":  bestScore,
		}
		c.ServeJSON()
		return
	}

	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
		"data":       matchedFile.FilePath,
		"bestMatch":  bestMatch,
		"bestScore":  bestScore,
		"fileName":   fileName,
	}
	c.ServeJSON()
}

// 删除历史记录
type DeleteHistoryRecordRequest struct {
	AIConversationID uint64 `json:"ai_conversation_id"`
}

func (c *ChatController) DeleteHistoryRecord() {
	var requestData DeleteHistoryRecordRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	ai_conversation_id := requestData.AIConversationID
	tx := models.DB.Begin()
	if err := tx.Model(&models.AIConversation{}).Where("id = ?", ai_conversation_id).Update("is_deleted", 1).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "删除历史记录失败",
		}
	}
	tx.Commit()
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
	}
	c.ServeJSON()
}

// 删除隐患识别的历史记录
type DeleteRecognitionRecordRequest struct {
	RecognitionRecordID uint64 `json:"recognition_record_id"`
}

func (c *ChatController) DeleteRecognitionRecord() {
	var requestData DeleteRecognitionRecordRequest
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestData); err != nil {
		c.Data["json"] = map[string]interface{}{
			"statusCode": 400,
			"msg":        "请求数据解析失败",
		}
		c.ServeJSON()
		return
	}
	recognition_record_id := requestData.RecognitionRecordID
	tx := models.DB.Begin()
	if err := tx.Model(&models.RecognitionRecord{}).Where("id = ?", recognition_record_id).Update("is_deleted", 1).Error; err != nil {
		tx.Rollback()
		c.Data["json"] = map[string]interface{}{
			"statusCode": 500,
			"msg":        "删除隐患识别的历史记录失败",
		}
		c.ServeJSON()
		return
	}
	tx.Commit()
	c.Data["json"] = map[string]interface{}{
		"statusCode": 200,
		"msg":        "success",
	}
	c.ServeJSON()
}
